package com.lanchetech.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.dto.TenantFeatureDTO;
import com.lanchetech.bean.request.TenantPageReq;
import com.lanchetech.bean.response.SpuResp;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.AccessType;
import com.lanchetech.common.enums.ActivityEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.CardConsumptionFundService;
import com.lanchetech.bean.dto.CardConsumptionFundDto;
import com.lanchetech.bean.request.CardConsumptionFundItemReq;
import com.lanchetech.bean.request.CardConsumptionFundReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.common.enums.CardConsumptionFundItemEnum;
import com.lanchetech.common.enums.ResultCode;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.common.util.ObjectUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CardConsumptionFundServiceImpl implements CardConsumptionFundService {

    @Autowired
    private CardConsumptionFundMapper cardConsumptionFundMapper;
    @Autowired
    private CardConsumptionFundItemMapper cardConsumptionFundItemMapper;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private CardConsumptionUserMapper cardConsumptionUserMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private TenantMapper tenantMapper;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private OrderSkuMapper orderSkuMapper;

    @Override
    public int save(CardConsumptionFund cardConsumptionFund) throws ResultCodeException {
//        if (StringUtils.isEmpty(cardConsumptionFund.getCardCode())) {
//            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_CODE);
//        }
        if (StringUtils.isBlank(cardConsumptionFund.getCardImage())) {
            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_IMAGE);
        }
//        CardConsumptionFund cardCode = cardConsumptionFundMapper.getByCardCode(cardConsumptionFund.getCardCode());
        // 编辑
        if (cardConsumptionFund.getId() != null) {
//            if (!cardCode.getId().equals(cardConsumptionFund.getId())) {
//                throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_CARD_CODE);
//            }
            cardConsumptionFund.setWhether(false);
            cardConsumptionFundMapper.updateByPrimaryKey(cardConsumptionFund);
            redisTemplate.delete("myConsumptionFund");
            return cardConsumptionFund.getId().intValue();
        }
        // 新增
//        if (cardCode != null) {
//            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_CARD_CODE);
//        }
        cardConsumptionFund.setCreated(new Date());
        CardConsumptionFundDto dto = ObjectUtil.copy(cardConsumptionFund, CardConsumptionFundDto.class);
        return cardConsumptionFundMapper.insert(dto);
    }

    @Override
    public ResultData<BasePageResp<CardConsumptionFundVo>> list(CardConsumptionFundReq cardConsumptionFundReq) {
        Page page = PageHelper.startPage(cardConsumptionFundReq.getPageNum(), cardConsumptionFundReq.getPageSize());
        List<CardConsumptionFundVo> cardConsumptionFund = cardConsumptionFundMapper.findAll(cardConsumptionFundReq);
        return PageHelpUtil.buildPage(cardConsumptionFund, page);
    }

    @Override
    public void whether(Long id, boolean whether) throws ResultCodeException {
        CardConsumptionFund consumptionFund = cardConsumptionFundMapper.selectByPrimaryKey(id);
        if (consumptionFund == null) {
            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_NULL);
        }
        if (whether) {
            // 有无开启中的消费金
            int count = cardConsumptionFundMapper.whether(id);
            if (count > 0) {
                throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_WHETHER);
            }
        }
        consumptionFund.setWhether(whether);
        cardConsumptionFundMapper.updateByPrimaryKey(consumptionFund);
    }

    @Override
    public ResultData<BasePageResp<CardConsumptionFundItemVo>> applySpu(CardConsumptionFundItemReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        req.setDeleted(false);
        List<CardConsumptionFundItemVo> vos = cardConsumptionFundItemMapper.getSpuByCardConsumptionFundId(req);
        if (CollectionUtils.isNotEmpty(vos)) {
            for (CardConsumptionFundItemVo vo : vos) {
                SpuItemVO spu = spuMapper.getSpuById(vo.getSpuId());
                if (spu == null) {
                    continue;
                }
                List<Sku> skuList = skuMapper.findAllBySpuId(vo.getSpuId());
                spu.setSkuList(skuList);
                vo.setSpu(spu);
            }
        }
        return PageHelpUtil.buildPage(vos, page);
    }

    @Override
    public void examineSpu(CardConsumptionFundItemReq req) throws ResultCodeException {
        // 获取消费金
        CardConsumptionFund consumptionFund = cardConsumptionFundMapper.selectByPrimaryKey(req.getCardConsumptionFundId());
        // 是否存在 是否已删除
        if (consumptionFund == null || consumptionFund.isDeleted()) {
            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_NULL);
        }
        // 商品是否存在
        SpuItemVO spu = spuMapper.getSpuById(req.getSpuId());
        if (spu == null) {
            throw new ResultCodeException(ResultCode.SPU_EXCEPTION);
        }
        // 获取消费金绑定商品
        CardConsumptionFundItem item = cardConsumptionFundItemMapper.getOneFundItemBySupId(consumptionFund.getId(), spu.getId());
        // 审核拒绝 更改审核状态
        if (CardConsumptionFundItemEnum.REJECT.getStatus().equals(req.getStatus())) {
            if (StringUtils.isBlank(req.getRemark())) {
                throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_ACCOUNT);
            }
            item.setStatus(CardConsumptionFundItemEnum.REJECT.getStatus());
            item.setRemark(req.getRemark());
            cardConsumptionFundItemMapper.updateByPrimaryKey(item);
            return;
        }
        // 审核通过 更改审核状态
        item.setStatus(CardConsumptionFundItemEnum.PASS.getStatus());
        cardConsumptionFundItemMapper.updateByPrimaryKey(item);
    }

    @Override
    public void apply(List<CardConsumptionFundItem> cardConsumptionFundItems, List<String> strings) throws ResultCodeException {
        if (CollectionUtils.isEmpty(cardConsumptionFundItems)) {
            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_ITEM);
        }
        CardConsumptionFund cardConsumptionFund = cardConsumptionFundMapper.selectByPrimaryKey(cardConsumptionFundItems.get(0).getCardConsumptionFundId());
        if (cardConsumptionFund == null || cardConsumptionFund.isDeleted()) {
            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_ACTIVITY_IS_NULL);
        }
        List<CardConsumptionFundItem> list = new ArrayList<>();
        for (CardConsumptionFundItem cardConsumptionFundItem : cardConsumptionFundItems) {
            // 查看当前绑定商品有无绑定
            CardConsumptionFundVo cardConsumptionFundVo = cardConsumptionFundItemMapper.getBySpuIdAndFundId(cardConsumptionFundItem.getCardConsumptionFundId(), cardConsumptionFundItem.getSpuId());
            if (cardConsumptionFundVo != null) {
                strings.add(cardConsumptionFundItem.getSpuId() + "已绑定,卡号为:" + cardConsumptionFundVo.getCardCode());
                continue;
            }
            list.add(cardConsumptionFundItem);
        }
        if (CollectionUtils.isNotEmpty(list)) {
            cardConsumptionFundItemMapper.insertApply(list);
        }
    }

    @Override
    public void deleted(Long id) throws ResultCodeException {
        CardConsumptionFundItem cardConsumptionFundItem = cardConsumptionFundItemMapper.selectByPrimaryKey(id);
        if (cardConsumptionFundItem == null) {
            throw new ResultCodeException(ResultCode.CARD_CONSUMPTION_FUND_SPU_IS_NULL);
        }
        cardConsumptionFundItem.setDeleted(true);
        cardConsumptionFundItemMapper.updateByPrimaryKey(cardConsumptionFundItem);
    }

    @Override
    public CardConsumptionFund findOne() {
        return cardConsumptionFundMapper.findOne();
    }

    @Override
    public void insertCardConsumptionUser(CardConsumptionUser cardConsumptionUser) {
        cardConsumptionUserMapper.insertCardConsumptionUser(cardConsumptionUser);
    }

    @Override
    public CardConsumptionUser getCardConsumptionUser(Long id) {
        return ObjectUtil.copy(cardConsumptionUserMapper.getCardConsumptionUser(id), CardConsumptionUser.class);
    }

    @Override
    public ResultData<BasePageResp<CardConsumptionFundItemVo>> getBindSpu(CardConsumptionFundItemReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        req.setDeleted(false);
        if (req.getAccessType().equals(AccessType.MINI)) {
            List<CardConsumptionFundItemVo> cardConsumptionFundItemVos = cardConsumptionFundItemMapper.findAll(req);
            if (CollectionUtils.isNotEmpty(cardConsumptionFundItemVos)) {
                calculatePrice(req.getUserId(), cardConsumptionFundItemVos);
            }
            return PageHelpUtil.buildPage(cardConsumptionFundItemVos, page);
        }
        List<CardConsumptionFundItemVo> cardConsumptionFundItemVos = cardConsumptionFundItemMapper.findAll(req);
        return PageHelpUtil.buildPage(cardConsumptionFundItemVos, page);
    }

    /**
     * 计算消费金折扣金额
     *
     * @param userId                     用户ID
     * @param cardConsumptionFundItemVos 消费金商品
     */
    public void calculatePrice(Long userId,
                               List<CardConsumptionFundItemVo> cardConsumptionFundItemVos) {
        // 判断用户是否为首次折扣
        int count = orderSkuMapper.getOrderSkuByUserId(userId, ActivityEnum.CONSUMPTION_FUND.getActivity());
        for (CardConsumptionFundItemVo fundItemVo : cardConsumptionFundItemVos) {
            SpuItemVO spuItemVO = spuMapper.getSpuById(fundItemVo.getSpuId());
            if (count > 0) {
                fundItemVo.setDeduction(spuItemVO.getMinPrice().multiply(fundItemVo.getFollowDiscount()));
            } else {
                fundItemVo.setDeduction(spuItemVO.getMinPrice().multiply(fundItemVo.getFirstDiscount()));
            }
            fundItemVo.setSpu(spuMapper.getSpuById(fundItemVo.getSpuId()));
            fundItemVo.setSkuList(skuMapper.findAllBySpuId(fundItemVo.getSpuId()));
        }
    }

    @Override
    public ResultData<CardConsumptionUserVo> get(User user) {
        if (user == null) {
            return new ResultData<>();
        }
//        // 查找缓存是否存在
//        ValueOperations<String, CardConsumptionUserVo> operations = redisTemplate.opsForValue();
//        CardConsumptionUserVo consumptionFund = operations.get("myConsumptionFund:" + user.getId());
//        if (consumptionFund != null) {
//            return new ResultData<>(consumptionFund);
//        }
        CardConsumptionUserVo vo = cardConsumptionUserMapper.getCardConsumptionUser(user.getId());
//        if (vo != null) {
//            String key = "myConsumptionFund:" + user.getId();
//            operations.set(key, vo, 24, TimeUnit.HOURS);
//        }
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<BasePageResp<StoreDetailVO>> getCardStore(TenantPageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        // 获取消费金商家
        List<CardConsumptionFundItemVo> cardConsumptionFundItemVos = cardConsumptionFundItemMapper.getTenantId(req);
        if (CollectionUtils.isNotEmpty(cardConsumptionFundItemVos)) {
            List<StoreDetailVO> vos = calculate(cardConsumptionFundItemVos);
            return PageHelpUtil.buildPage(vos, page);
        }
        return new ResultData<>();
    }

    /**
     * @param cardConsumptionFundItemVos 消费金商品
     * @return 商家信息
     */
    public List<StoreDetailVO> calculate(List<CardConsumptionFundItemVo> cardConsumptionFundItemVos) {
        List<StoreDetailVO> vos = new ArrayList<>();
        cardConsumptionFundItemVos.forEach(cardConsumptionFundItemVo -> {
            StoreDetailVO vo = new StoreDetailVO();
            Long tenantId = cardConsumptionFundItemVo.getTenantId();
            Tenant tenant = tenantMapper.selectByPrimaryKey(tenantId);
            Shop shop = shopMapper.selectByPrimaryKey(tenantId);
            TenantInfoVO info = shopMapper.getTenantInfoById(tenantId);
            if (tenant != null) {
                info.setMerchantId(tenant.getMerchantId());
                info.setFeature(tenant.getFeature());
                info.setImageUrl(tenant.getImageUrl());
                info.setDescription(tenant.getDescription());
            }
            info.setTenantName(shop.getShopName());
            info.setServiceStar(Double.valueOf(shop.getServiceStar().toString()));
            info.setEnvironmentStar(Double.valueOf(shop.getEnvironmentStar().toString()));
            info.setValueStar(shop.getValueStar().doubleValue());
            info.setSpuNumber(spuMapper.countByTenantId(shop.getId()));
            info.setShopLevel(shop.getShopLevel());
            info.setHighDiscount(cardConsumptionFundItemVo.getFollowDiscount());
            info.setLowDiscount(cardConsumptionFundItemVo.getFirstDiscount());
            vo.setTenantInfoVO(info);
            vos.add(vo);
        });
        return vos;
    }

    @Override
    public ResultData<BasePageResp<CardConsumptionFundItemVo>> getStoreSpu(CardConsumptionFundItemReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        req.setDeleted(false);
        List<CardConsumptionFundItemVo> cardConsumptionFundItemVos = cardConsumptionFundItemMapper.findAll(req);
        if (CollectionUtils.isNotEmpty(cardConsumptionFundItemVos)) {
            for (CardConsumptionFundItemVo fundItemVo : cardConsumptionFundItemVos) {
                SpuItemVO spuItemVO = spuMapper.getSpuById(fundItemVo.getSpuId());
                fundItemVo.setDeduction(spuItemVO.getMinPrice().multiply(fundItemVo.getFirstDiscount()));
                fundItemVo.setSpu(spuMapper.getSpuById(fundItemVo.getSpuId()));
                fundItemVo.setSkuList(skuMapper.findAllBySpuId(fundItemVo.getSpuId()));
            }
        }
        return PageHelpUtil.buildPage(cardConsumptionFundItemVos, page);
    }
}
